#include "adreno_cmd.h"

uint cp_gpuaddr(uint *cmds, uint64_t gpuaddr)
{
    uint *start = cmds;

    *cmds++ = lower_32_bits(gpuaddr);
    *cmds++ = upper_32_bits(gpuaddr);

    return cmds - start;
}

uint pm4_calc_odd_parity_bit(uint val) {
    return (0x9669 >> (0xf & ((val) ^
                              ((val) >> 4) ^ ((val) >> 8) ^ ((val) >> 12) ^
                              ((val) >> 16) ^ ((val) >> 20) ^ ((val) >> 24) ^
                              ((val) >> 28)))) & 1;
}

uint cp_type7_packet(uint opcode, uint cnt) {
    return CP_TYPE7_PKT | ((cnt) << 0) |
           (pm4_calc_odd_parity_bit(cnt) << 15) |
           (((opcode) & 0x7F) << 16) |
           ((pm4_calc_odd_parity_bit(opcode) << 23));
}

uint cp_wait_for_me(
        uint *cmds)
{
    uint *start = cmds;

    *cmds++ = cp_type7_packet(CP_WAIT_FOR_ME, 0);

    return cmds - start;
}

uint cp_mem_packet(int opcode, uint size, uint num_mem) {
    return cp_type7_packet(opcode, size + num_mem);
}

uint cp_wait_for_idle(
        uint *cmds)
{
    uint *start = cmds;

    *cmds++ = cp_type7_packet(CP_WAIT_FOR_IDLE, 0);

    return cmds - start;
}

uint cp_type4_packet(uint opcode, uint cnt)
{
    return CP_TYPE4_PKT | ((cnt) << 0) |
           (pm4_calc_odd_parity_bit(cnt) << 7) |
           (((opcode) & 0x3FFFF) << 8) |
           ((pm4_calc_odd_parity_bit(opcode) << 27));
}

uint cp_register(
        unsigned int reg, unsigned int size)
{
    return cp_type4_packet(reg, size);
}

uint cp_invalidate_state(
        uint *cmds)
{
    uint *start = cmds;

    *cmds++ = cp_type7_packet(CP_SET_DRAW_STATE, 3);
    *cmds++ = 0x40000;
    *cmds++ = 0;
    *cmds++ = 0;

    return cmds - start;
}
